package com.hk.player;

import android.content.Context;
import android.graphics.Bitmap;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.TextureView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.hk.player.core.DataCallback;
import com.hk.player.core.IHKPlayerView;
import com.hk.player.core.MonitorMediaData;
import com.hk.player.core.OnMuteChangeListener;
import com.hk.player.core.OnUiHiddenListener;
import com.hk.player.core.Protocol;
import com.hk.player.utils.PlayerDataManager;
import com.hk.player.utils.PlayerProviderManager;
import com.zhoug.common.framework.glide.wrap.GlideHelper;
import com.zhoug.common.prodivers.CornerViewOutlineProvider;
import com.zhoug.common.screenrecord.OnRecordVideoListener;
import com.zhoug.common.utils.BitmapUtils;
import com.zhoug.common.utils.LogUtils;
import com.zhoug.common.utils.StringUtils;
import com.zhoug.common.utils.ToastUtils;
import com.zhoug.player.core.OnTalkListener;
import com.zhoug.player.hikvision.HikTalkHelper;

import java.io.File;
import java.util.Objects;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.reactivex.disposables.Disposable;

/**
 * @author: zhoug
 * @since: 2025-08-04
 */
public abstract class AbsPlayerView extends FrameLayout implements IHKPlayerView {
    private static final String TAG = ">>>AbsPlayerView";
    private boolean isInit = false;//布局是否完成
    protected int mProtocol = Protocol.HLS;//视频播放地址的协议
    protected static final int RETRY_MAX_COUNT = 5;//播放失败最大重试次数
    protected MonitorMediaData mMediaData;//视频媒体资源
    protected boolean mAutoStopOnMonitorChange;//播放资源改变时是否停止播放
    protected ImageView mIvPlace;//封面占位图
    private ProgressBar mProgressBar;//进度
    private ImageView mBtnPlay;//播放按钮
    private TextView mTvError;//错误提示

    private boolean waterMarkerEnable = true;//默认启用水印
    private int windowCorner = 0;//播放窗口圆角
    public boolean mMute = true;//默认静音

    private OnUiHiddenListener onUiHiddenListener;//ui显示隐藏监听
    protected OnRecordVideoListener onRecordVideoListener;//录像监听器
    protected OnMuteChangeListener onMuteChangeListener;//声音开关监听
    protected OnTalkListener onTalkListener;//对讲监听
    private HikTalkHelper mTalkHelper;

    private boolean btnPlayStatus = false;//播放按钮的状态
    protected volatile boolean recording = false;//是否正在录像
    protected int mRetryCount = 0;//当前播放失败重试次数
    private boolean autoHidePlayBtn = true;//自动隐藏播放按钮
    private static final int autoHidePlayBtnTime = 5000;

    private PlayerWindowView mPlayWindowView;
    private final Watermark mWatermark = new Watermark();
    private OnPlayBtnClickListener mOnPlayBtnClickListener;

    public AbsPlayerView(@NonNull Context context) {
        this(context, null);
    }

    public AbsPlayerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AbsPlayerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public AbsPlayerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initView();
    }

    /**
     * 设置是否自动隐藏播放按钮
     *
     * @param autoHidePlayBtn 默认:true
     */
    @Override
    public void setAutoHidePlayBtn(boolean autoHidePlayBtn) {
        this.autoHidePlayBtn = autoHidePlayBtn;
    }

    /**
     * 设置播放窗口圆角
     *
     * @param windowCorner >0显示圆角
     */
    @Override
    public void setWindowCorner(int windowCorner) {
        this.windowCorner = windowCorner;
    }

    /**
     * 是否显示水印
     *
     * @param waterMarkerEnable true:显示水印
     */
    @Override
    public void setWaterMarkerEnable(boolean waterMarkerEnable) {
        this.waterMarkerEnable = waterMarkerEnable;
    }

    /**
     * 设置播放按钮点击监听
     *
     * @param onPlayBtnClickListener OnPlayBtnClickListener
     */
    @Override
    public void setOnPlayBtnClickListener(OnPlayBtnClickListener onPlayBtnClickListener) {
        this.mOnPlayBtnClickListener = onPlayBtnClickListener;
    }


    /**
     * 初始化布局和点击事件
     */
    private void initView() {
        if (isInit) return;
        View mRoot = LayoutInflater.from(getContext()).inflate(R.layout.hk_player_player_view, this, false);
        addView(mRoot);
        mIvPlace = mRoot.findViewById(R.id.iv_place);
        mProgressBar = mRoot.findViewById(R.id.progressBar);
        mBtnPlay = mRoot.findViewById(R.id.btn_play);
        mTvError = mRoot.findViewById(R.id.tv_error);
        mPlayWindowView = mRoot.findViewById(R.id.playWindowView);

        //初始化水印
        Watermark watermark = PlayerDataManager.getInstance().getWatermark();
        if (watermark != null) {
            mWatermark.setWaterMark(watermark.getWaterMark());
            mWatermark.setShowWatermark(watermark.isShowWatermark());
        }
        drawRadius();
        //播放按钮监听
        mBtnPlay.setOnClickListener(v -> {
            if (btnPlayStatus) {
                pausePlay();
                btnPlayStatus = false;
            } else {
                mRetryCount = 0;
                startPlay();
                btnPlayStatus = true;
            }
            if (mOnPlayBtnClickListener != null) {
                mOnPlayBtnClickListener.onPlayBtnClick(this, btnPlayStatus);
            }
        });

        //设置单击改变ui显示状态
        mPlayWindowView.setOnClickListener(v -> {
            if (mBtnPlay != null) {
                boolean visibility = mBtnPlay.getVisibility() != View.VISIBLE;
                setPlayButtonVisibility(visibility);


            }

        });
        isInit = true;
        onViewCreated();
    }

    /**
     * 设置播放资源
     *
     * @param monitorData {@link MonitorMediaData}
     */
    @Override
    public void setMonitorData(MonitorMediaData monitorData) {
        if (mMediaData == null) {
            this.mMediaData = monitorData;
            setVideoCoverImage(true);
        } else if (!Objects.equals(mMediaData, monitorData)) {
            this.mMediaData = monitorData;
            if (mAutoStopOnMonitorChange) {
                //播放资源改变
                stopPlay();
                setVideoCoverImage(true);
            }
        }
    }

    @Override
    public void setAutoStopOnMonitorChange(boolean autoStopOnMonitorChange) {
        this.mAutoStopOnMonitorChange = autoStopOnMonitorChange;
    }

    @Override
    public MonitorMediaData getMonitorData() {
        return mMediaData;
    }

    /**
     * 播放画面 TextureView
     *
     * @return TextureView
     */
    protected TextureView getTextureView() {
        return mPlayWindowView.getTextureView();
    }

    /**
     * 播放画面窗口
     *
     * @return PlayerWindowView
     */
    protected PlayerWindowView getPlayWindowView() {
        return mPlayWindowView;
    }

    /**
     * s设置圆角
     */
    private void drawRadius() {
        if (windowCorner > 0) {
            CornerViewOutlineProvider cp = new CornerViewOutlineProvider(windowCorner);
//            mRoot.setOutlineProvider(new CornerViewOutlineProvider(radius));
//            mRoot.setClipToOutline(true);
            mPlayWindowView.getTextureView().setOutlineProvider(cp);
            mPlayWindowView.getTextureView().setClipToOutline(true);
            mIvPlace.setOutlineProvider(cp);
            mIvPlace.setClipToOutline(true);
            mPlayWindowView.getWatermarkImageView().setOutlineProvider(cp);
            mPlayWindowView.getWatermarkImageView().setClipToOutline(true);
//            mIvPlace.setCorners(corner);
//            mIvWatermark.setCorners(corner);
        }

    }

    /**
     * 设置视频封面的显示状态
     *
     * @param visibility true:显示视频封面
     */
    protected void setVideoCoverImage(boolean visibility) {
        try {

            if (visibility && mIvPlace != null) {
                mIvPlace.setVisibility(View.VISIBLE);
                String imageUrl = mMediaData != null ? mMediaData.getVideoCoverImage() : null;
                //加载视频封面
                if (!StringUtils.isNullOrEmpty(imageUrl)) {
                    GlideHelper.with(getContext())
                            .load(imageUrl)
                            .placeholder(R.drawable.hk_player_video_cover_image)
                            .error(R.drawable.hk_player_video_cover_image)
                            .into(mIvPlace);
                } else {
                    String cacheImage = getCacheImage();
                    //加载视频截图作为封面
                    if (imageExists(cacheImage)) {
                        GlideHelper.with(getContext())
                                .placeholder(R.drawable.hk_player_video_cover_image)
                                .error(R.drawable.hk_player_video_cover_image)
                                .load(cacheImage)//防止缓存不刷新图片
                                .into(mIvPlace);
                    } else {
                        //加载资源文件中设置的默认视频封面图片
                        GlideHelper.with(getContext())
                                .load(R.drawable.hk_player_video_cover_image)
                                .into(mIvPlace);
                    }
                }
            } else if (mIvPlace != null) {
                mIvPlace.setVisibility(View.GONE);
            }
        } catch (Exception e) {
            LogUtils.e(TAG, "setVideoCoverImage:" + e.getMessage());
        }
        showWatermark(!visibility);
    }

    /**
     * 改变播放按钮状态
     *
     * @param btnPlayStatus 是否在播放
     */
    protected void setPlayButtonStatus(boolean btnPlayStatus) {
        if (mBtnPlay != null) {
            if (btnPlayStatus) {
                mBtnPlay.setImageResource(R.drawable.hk_player_icon_play);
            } else {
                mBtnPlay.setImageResource(R.drawable.hk_player_icon_stop);
            }
            startAutoHidePlayBtnRunnable();
            this.btnPlayStatus = btnPlayStatus;
        }
    }

    /**
     * 显示/隐藏播放按钮
     *
     * @param visibility true:显示播放按钮
     */
    protected void setPlayButtonVisibility(boolean visibility) {
        if (mBtnPlay != null) {
            mBtnPlay.setVisibility(visibility ? View.VISIBLE : View.GONE);
            if (visibility) {
                startAutoHidePlayBtnRunnable();
            }
            if (onUiHiddenListener != null) {
                onUiHiddenListener.onCallback(visibility);
            }
        }

    }

    /**
     * 一段时间后自动隐藏播放按钮
     */
    private void startAutoHidePlayBtnRunnable() {
        if (mBtnPlay != null && autoHidePlayBtn && mBtnPlay.getVisibility() == View.VISIBLE) {
            mBtnPlay.removeCallbacks(autoHidePlayBtnRunnable);
            mBtnPlay.postDelayed(autoHidePlayBtnRunnable, autoHidePlayBtnTime);
        }
    }

    /**
     * 隐藏播放按钮的任务
     */
    private final Runnable autoHidePlayBtnRunnable = new Runnable() {
        @Override
        public void run() {
            if (mBtnPlay != null) {
                setPlayButtonVisibility(false);
            }
        }
    };

    /**
     * 显示错误信息
     *
     * @param error 错误信息
     */
    protected void showError(String error) {
        if (mTvError == null) {
            return;
        }
        if (error == null) {
            mTvError.setText("");
            mTvError.setVisibility(View.GONE);
        } else {
            mTvError.setText(error);
            mTvError.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 隐藏错误信息
     */
    protected void hideError() {
        if (mTvError != null) {
            mTvError.setText("");
            mTvError.setVisibility(View.GONE);
        }
    }

    /**
     * 显示正在加载框
     */
    protected void showPlayLoading() {
        if (mProgressBar != null) {
            mProgressBar.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 隐藏视频加载框
     */
    protected void cancelPlayLoading() {
        if (mProgressBar != null) {
            mProgressBar.setVisibility(View.GONE);
        }
    }


    /**
     * 布局文件初始化完成后执行
     */
    protected abstract void onViewCreated();


    /**
     * 停止播放
     */
    protected abstract void _stopPlay();


    /**
     * 预加载视频
     */
    public abstract void preload();


    /**
     * 停止播放
     */
    @Override
    public final void stopPlay() {
        //截取最后一张图片作为封面
        if (isPlaying()) {
            captureCacheImage();
        }
        cancelRequest();
        cancelPlayLoading();
        setPlayButtonStatus(false);
        setVideoCoverImage(true);
        _stopPlay();
    }


    /**
     * 释放播放器资源
     */
    @Override
    public void releasePlayer() {
        cancelRequest();
        stopPlay();
        mRetryCount = 0;

    }


    /**
     * 是否是静音
     *
     * @return 是否静音
     */
    public abstract boolean isMute();

    /**
     * 截取视频图片
     *
     * @param path 图片保存路径
     * @return 是否成功
     */
    public boolean capturePicture(String path) {
        boolean success = false;
        if (getTextureView() != null && isPlaying()) {
            Bitmap bitmap = getTextureView().getBitmap();
            if (bitmap != null) {
                success = BitmapUtils.keepBitmap(bitmap, 100, path);
            }
        }
        return success;
    }


    /**
     * 是否正在录像
     *
     * @return 是否正在录像
     */
    public boolean isRecording() {
        return recording;
    }

    /**
     * 开始对讲
     */
    public void startTalk() {
        if (mTalkHelper == null) {
            mTalkHelper = new HikTalkHelper();
        } else {
            if (mTalkHelper.isTalking()) {
                return;
            }
        }
        LogUtils.d(TAG, "stopVoiceTalk:开始对讲");
        mTalkHelper.setOnTalkListener(new com.zhoug.player.core.OnTalkListener() {
            @Override
            public void onTalkCallback(int status, String error) {
                if (onTalkListener != null) {
                    switch (status) {
                        case com.zhoug.player.core.OnTalkListener.LOADING:
                            onTalkListener.onTalkCallback(OnTalkListener.LOADING, error);
                            break;
                        case com.zhoug.player.core.OnTalkListener.SUCCESS:
                            onTalkListener.onTalkCallback(OnTalkListener.SUCCESS, error);
                            break;
                        case com.zhoug.player.core.OnTalkListener.CLOSE:
                            onTalkListener.onTalkCallback(OnTalkListener.CLOSE, error);
                            break;
                        case com.zhoug.player.core.OnTalkListener.FAILED:
                            onTalkListener.onTalkCallback(OnTalkListener.FAILED, error);
                            break;
                        case com.zhoug.player.core.OnTalkListener.EXCEPTION:
                            onTalkListener.onTalkCallback(OnTalkListener.EXCEPTION, error);
                            break;
                    }
                }

            }
        });
        if (onTalkListener != null) {
            onTalkListener.onTalkCallback(OnTalkListener.LOADING, "正在请求对讲url");
        }
        getMonitorTalkUrl(new DataCallback<MonitorMediaData>() {
            @Override
            public void onSuccess(MonitorMediaData mediaData) {
                if (mediaData != null && !StringUtils.isNullOrEmpty(mediaData.getTalkUrl())) {
                    String talkUrl = mediaData.getTalkUrl();
                    LogUtils.d(TAG, "startPlay:talkUrl=" + talkUrl);
                    if (mTalkHelper != null) {
                        mTalkHelper.setTalkUrl(talkUrl);
                        mTalkHelper.startVoiceTalk();
                    } else {
                        if (onTalkListener != null) {
                            onTalkListener.onTalkCallback(OnTalkListener.FAILED, "初始化SDK失败");
                        }
                    }
                } else {
                    if (onTalkListener != null) {
                        onTalkListener.onTalkCallback(OnTalkListener.FAILED, "对讲url为空");
                    }
                }
            }

            @Override
            public void onFailure(String error) {
                if (onTalkListener != null) {
                    onTalkListener.onTalkCallback(OnTalkListener.FAILED, "请求对讲url失败:" + error);
                }
            }
        });
    }

    /**
     * 停止对讲
     */
    public void stopTalk() {
        if (mTalkHelper != null) {
            LogUtils.d(TAG, "stopVoiceTalk:停止对讲");
            mTalkHelper.stopVoiceTalk();
        }
    }


    /**
     * 开始录像
     *
     * @param path 录像文件保存地址
     */
    public void startRecord(@NonNull String path) {


    }

    /**
     * 停止录像
     */
    public void stopRecord() {

    }

    /**
     * 设置录像监听
     *
     * @param onRecordVideoListener 像监听
     */
    public void setOnRecordVideoListener(OnRecordVideoListener onRecordVideoListener) {
        this.onRecordVideoListener = onRecordVideoListener;
    }

    /**
     * 获取录像监听器
     *
     * @return OnRecordVideoListener
     */
    protected OnRecordVideoListener getOnRecordVideoListener() {
        return onRecordVideoListener;
    }

    /**
     * 设置静音改变监听器
     *
     * @param onMuteChangeListener 静音改变监听器
     */
    public void setOnMuteChangeListener(OnMuteChangeListener onMuteChangeListener) {
        this.onMuteChangeListener = onMuteChangeListener;
    }

    /**
     * 设置对讲监听器
     *
     * @param onTalkListener 对讲监听器
     */
    public void setOnTalkListener(OnTalkListener onTalkListener) {
        this.onTalkListener = onTalkListener;
    }

    /**
     * 设置视频控制组件显示状态改变监听器
     *
     * @param onUiHiddenListener 视频控制组件显示状态改变监听器
     */
    public void setOnUiHiddenListener(OnUiHiddenListener onUiHiddenListener) {
        this.onUiHiddenListener = onUiHiddenListener;
    }

    /**
     * 获取缓存占位图的path
     *
     * @return 位图的path
     */
    protected String getCacheImage() {
        if (getContext() != null) {
            File cacheDir = getContext().getCacheDir();
            if (mMediaData != null && mMediaData.getMonitorId() != null) {
                File file = new File(cacheDir, "video_cover/" + mMediaData.getMonitorId() + ".jpg");
                File parentFile = file.getParentFile();
                if (parentFile != null && !parentFile.exists()) {
                    boolean mkdirs = parentFile.mkdirs();
                    if (!mkdirs) {
                        LogUtils.e(TAG, "视频封面缓存图片目录创建失败");
                    }
                }
                return file.getAbsolutePath();

            }
        }
        return null;
    }

    /**
     * 判断图片是否存在
     *
     * @param path 图片路径
     * @return 是否存在
     */
    private boolean imageExists(String path) {
        if (path != null) {
            File file = new File(path);
            return file.exists() && file.length() > 0;
        }
        return false;
    }

    /**
     * 截取视频图片
     */
    private void captureCacheImage() {
        String cacheImage = getCacheImage();
        if (cacheImage != null) {
            boolean b = capturePicture(cacheImage);
            if (b) {
                LogUtils.d(TAG, "截图成功");
            } else {
                LogUtils.e(TAG, "截图失败");
            }
        }
    }

    /**
     * 截取视频图片 延时一定时间后执行
     */
    protected void captureCacheImageDelay() {
        if (mIvPlace != null) {
            mIvPlace.postDelayed(this::captureCacheImage, 1500);
        }
    }

    /**
     * 取消全部请求
     */
    protected void cancelRequest() {
        cancelRequest(mPlayUrlDisposable);
        cancelRequest(mTalkUrlDisposable);
    }

    /**
     * 取消指定请求
     *
     * @param disposable Disposable
     */
    private void cancelRequest(Disposable disposable) {
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
    }


    private Disposable mPlayUrlDisposable;
    private Disposable mTalkUrlDisposable;

    /**
     * 获取视频的播放地址
     *
     * @param protocol {@link Protocol}
     * @param callback 回掉
     */
    protected void getMonitorPlayUrl(int protocol, @NonNull DataCallback<MonitorMediaData> callback) {
        if (mMediaData == null) {
            LogUtils.e(TAG, "mMediaData is null");
            callback.onFailure("MediaData is null");
            return;
        }
        LogUtils.d(TAG, "开始获取播放地址:" + mMediaData);
        mPlayUrlDisposable = PlayerProviderManager.getHkPlayerProvider().getMonitorPlayUrl(mMediaData, protocol, new DataCallback<MonitorMediaData>() {
            @Override
            public void onSuccess(MonitorMediaData mediaData) {
                if (mediaData != null && !StringUtils.isNullOrEmpty(mediaData.getRealPlayUrl())) {
                    callback.onSuccess(mediaData);
                } else {
                    callback.onFailure("没有获取到播放地址");
                }
            }

            @Override
            public void onFailure(String error) {
                callback.onFailure(error);
            }
        });
    }

    /**
     * 获取视频对讲地址
     *
     * @param callback 回掉
     */
    protected void getMonitorTalkUrl(@NonNull DataCallback<MonitorMediaData> callback) {
        if (mMediaData == null) {
            LogUtils.e(TAG, "mMediaData is null");
            callback.onFailure("MediaData is null");
            return;
        }
        LogUtils.d(TAG, "获取摄像头的对讲地址:" + mMediaData);
        mTalkUrlDisposable = PlayerProviderManager.getHkPlayerProvider().getMonitorTalkUrl(mMediaData, new DataCallback<MonitorMediaData>() {
            @Override
            public void onSuccess(MonitorMediaData mediaData) {
                if (mediaData != null && !StringUtils.isNullOrEmpty(mediaData.getTalkUrl())) {
                    callback.onSuccess(mediaData);
                } else {
                    callback.onFailure("没有获取到对讲地址");
                }
            }

            @Override
            public void onFailure(String error) {
                callback.onFailure(error);
            }
        });
    }


    /**
     * 显示/隐藏视频水印
     *
     * @param show true 显示水印
     */
    protected void showWatermark(boolean show) {
        if (mPlayWindowView == null || !waterMarkerEnable) {
            return;
        }
        mPlayWindowView.setWatermark(mWatermark);
        mPlayWindowView.showWatermark(show);
    }

    /**
     * Toast消息
     *
     * @param msg 消息
     */
    public void toast(Object msg) {
        ToastUtils.toastShort(getContext(), msg);
    }


}
